package semant.first_pass;

import util.List;
import semant.Env;
import symbol.Symbol;
import symbol.ClassInfo;
import syntaxtree.ClassDecl;
import syntaxtree.ClassDeclSimple;
import syntaxtree.ClassDeclExtends;
import syntaxtree.MethodDecl;
import syntaxtree.VarDecl;
import syntaxtree.VisitorAdapter;

final class ClassDeclHandler extends VisitorAdapter {

    private Env env;

    private ClassDeclHandler(Env e){
	super();
	env = e;
    }

    static void firstPass(Env e, ClassDecl cd){
	ClassDeclHandler h = new ClassDeclHandler(e);
	cd.accept(h);
    }

    public void visit(ClassDecl node){
    	Symbol name = Symbol.symbol(node.name.s);
    	ClassInfo cinfo = new ClassInfo(name);

	// coloca atributos da classe na tabela de simbolos
	for(List<VarDecl> vd = node.varList; vd != null; vd = vd.tail)
	    AttributeHandler.firstPass(env, cinfo, vd.head);

	// coloca metodos da classe na tabela de simbolos
	for(List<MethodDecl> md = node.methodList; md != null; md = md.tail)
	    MethodDeclHandler.firstPass(env, cinfo, md.head);

    	// coloca classe na tabela de simbolos
    	if(!env.classes.put(name, cinfo)){
	    env.err.Error(node, new Object[]{"Nome da classe redefinido",
					     "Simbolo: " + name});
    	}
    }

    public void visit(ClassDeclSimple node){
	visit((ClassDecl)node);
    }

    public void visit(ClassDeclExtends node){
	visit((ClassDecl)node);
    }

}
